package aterrizar;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import aterrizar.exceptions.CategoriaAvionInfructuosa;
import aterrizar.exceptions.ClaseAsientoDuplicadoException;
import aterrizar.exceptions.ClaseAsientoNoExistenteException;

public class Avion {

	private CategoriaAvion categoriaAvion;
	private Map<Clase, List<Asiento>> asientos;
	private double velocidad;
	private String marca;
	private String modelo;

	/**
	 * Crea un <code>Avion</code> y lo deja listo para que se le agreguen asientos.
	 * @post Invocar {@link Avion#crearAsientos(int, Clase)} para agregar asientos
	 * @param categoria
	 * @param marca
	 * @param modelo
	 * @param velocidad velocidad crucero en Km/h
	 * @throws CategoriaAvionInfructuosa 
	 */
	public Avion(CategoriaAvion categoria, String marca, String modelo, double velocidadPromedio) throws CategoriaAvionInfructuosa {
		this.categoriaAvion = categoria;
		this.marca = marca;
		this.modelo = modelo;
		this.velocidad = velocidadPromedio;
		this.asientos = new TreeMap<Clase, List<Asiento>>();
	}
	
	public CategoriaAvion getCategoriaAvion() {
		return categoriaAvion;
	}

	/**
	 * Devuelve la lista de asientos de una determinada clase
	 * @param clase
	 * @throws ClaseAsientoNoExistenteException
	 */
	public List<Asiento> getAsientos(Clase clase) throws ClaseAsientoNoExistenteException {
		if (! tieneAsientosClase(clase))
			throw new ClaseAsientoNoExistenteException();
		return this.asientos.get(clase);
	}
	
	/**
	 * @return un <code>Set</code> inmodificable con todas las <code>Clases</code> de asiento
	 */
	public Set<Clase> getClasesDeAsiento() {
		return Collections.unmodifiableSet(asientos.keySet());
	}

	public double getVelocidad() {
		return velocidad;
	}

	public String getMarca() {
		return marca;
	}

	public String getModelo() {
		return modelo;
	}
	
	/*public void aterrizar() {
		
	}

	public void despegar() {
		
	}*/
	
	/**
	 * Crea un conjunto de asientos de una determinada clase
	 * @param cantidad >0
	 * @param clase
	 * @throws ClaseAsientoDuplicadoException si ya se existen asientos de esa clase en el avion
	 */
	public void crearAsientos(int cantidad, Clase clase) throws ClaseAsientoDuplicadoException {
		if (tieneAsientosClase(clase))
			throw new ClaseAsientoDuplicadoException();
		
		List<Asiento> asientos = new ArrayList<Asiento>(cantidad);
		for (int i=0; i<cantidad; i++)
			asientos.add(new Asiento(clase));
		
		this.asientos.put(clase, asientos);
	}
	
	/**
	 * @param clase
	 * @return <code>true</code> si hay asientos de clase <code>clase</code>.
	 */
	public boolean tieneAsientosClase(Clase clase) {
		return this.asientos.containsKey(clase);
	}
	
	/**
	 * @param avion
	 * @return <code>true</code> si <code>this</code> puede hacer transbordo
	 * con el <code>Avion avion</code> (o sea, tienen clases de asientos en comun).
	 */
	public boolean puedeHacerTransbordo(Avion avion) {
		return ! Collections.disjoint(this.getClasesDeAsiento(), avion.getClasesDeAsiento());
	}

	/**
	 * @return Los aviones que pueden hacer transbordos entre 2 colecciones
	 */
	static Collection<Avion> getTransbordables(Collection<Avion> aviones1, Collection<Avion> aviones2) {
		for (Iterator<Avion> iAvion1 = aviones1.iterator(); iAvion1.hasNext();) {
			Avion avion1 = iAvion1.next();
			
			for (Avion avion2 : aviones2) {
				if (! avion1.puedeHacerTransbordo(avion2))
					// Elimino el avion que no pueda hacer transbordo
					iAvion1.remove();
			}
		}
		return aviones1;
	}
}
